# coding : utf-8

# http://m.biancheng.net/pandas/what-is-pandas.html
# https://matplotlib.org/stable/api/matplotlib_configuration_api.html
# https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.scatter.html
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import os
import re

#from pandasql import sqldf

class TA:
    def __init__(self, kwargs):
        self.set_acc = set()
        self.df = pd.DataFrame()
        plt = None
        self.kwargs=kwargs
        
    def get_acc_no_before(self, col_num=3):
        '''从交易文件中读取所有账号'''
        df = pd.read_table(self.kwargs['FILE']['filepath'],
                            sep=self.kwargs['FILE']['separator'], 
                            header=self.kwargs['FILE']['header'],
                            usecols=[col_num],
                            names=['acc_no'],
                            dtype={'acc_no':str},
                            encoding=self.kwargs['FILE']['encoding'],
                            error_bad_lines=False
                            )
                            
        for i in df['acc_no']:
            self.set_acc.add(i)
        print("账号数量合计：", len(self.set_acc))
        
    def get_data_chunk_columns(self, names, dtype, usecols, acc_no=None):
        """分区块读取交易数据文件，txt"""
        chunk_list = []
        df = pd.DataFrame()
        data_iterator = pd.read_table(self.kwargs['FILE']['filepath'],
                            sep=self.kwargs['FILE']['separator'], 
                            header=self.kwargs['FILE']['header'],
                            encoding=self.kwargs['FILE']['encoding'],
                            names=names,
                            dtype=dtype,
                            usecols=usecols,
                            chunksize=self.kwargs['FILE']['chunksize'],
                            error_bad_lines=False
                            )
        for data_chunk in data_iterator:
            df = df.append(data_chunk[data_chunk['Acc_no']==acc_no])
            #print(df)
        self.df = df
        
    def get_data_chunk(self, names, dtype, acc_no=None):
        """分区块读取交易数据文件，txt"""
        chunk_list = []
        df = pd.DataFrame()
        data_iterator = pd.read_table(self.kwargs['FILE']['filepath'],
                            sep=self.kwargs['FILE']['separator'], 
                            header=self.kwargs['FILE']['header'],
                            encoding=self.kwargs['FILE']['encoding'],
                            names=names,
                            dtype=dtype,
                            chunksize=self.kwargs['FILE']['chunksize'],
                            error_bad_lines=False
                            )
        for data_chunk in data_iterator:
            #print(df)
            df = df.append(data_chunk[data_chunk['Acc_no']==acc_no])
        self.df = df
        
    def get_data(self, names, dtype):
        """读取交易数据文件，txt"""
        self.df = pd.read_table(self.kwargs['FILE']['filepath'],
                    sep=self.kwargs['FILE']['separator'],
                    header=self.kwargs['FILE']['header'],
                    encoding=self.kwargs['FILE']['encoding'],
                    names=names,
                    dtype=dtype,
                    error_bad_lines=False
                    )
        # 打印数据的前5行
        #print(self.df.head())
        #print(self.df.dtypes)
        
    def get_acc_no(self):
        '''从交易文件中读取所有账号'''
        for i in self.df['Acc_no']:
            self.set_acc.add(i)
        print("账号数量合计：", len(self.set_acc))
        
    def flush_data(self):
        '''清洗数据'''
        self.df['Org_amt'] = self.df.apply(lambda x:x['Org_amt'] if x['Lend_flag']==self.kwargs['FILE']['lend_flag'] else x['Org_amt']*(-1), axis=1)
        self.df['Part_acc_no'] = self.df['Part_acc_no'].astype(str) #转字符串
        n = -1 * self.kwargs['FUNCTION']['length_acc']
        self.df['Part_acc_no'] = self.df['Part_acc_no'].apply(lambda x:x[n:]) #截取后10位
        self.df['Part_acc_no'] = self.df['Part_acc_no'].apply(lambda x:re.sub('\D','9',x)) #替换字母为数字
        # 打印数据的前5行
        #print(self.df.head())
        #print(self.df.dtypes)
        
    def extract_df(self, acc_no):
        '''抽取匹配条件的数据'''
        ex_df = self.df[self.df['Acc_no'].eq(acc_no)]
        #print(ex_df)
        return ex_df
        
    def construct_data(self):
        '''构造所需数据'''
        # 构造时间
        self.df['时间'] = self.df.apply(lambda x:x['Date']+' '+x['Time'],axis=1)
        self.df['时间'] = self.df['时间'].apply(lambda x:pd.Timestamp(x))
        #转换数据类型
        #self.df['Date'] = pd.to_datetime(self.df['Date'], format='%Y%m%d')
        #print(self.df['时间'])
        self.df['Part_acc_no'] = self.df['Part_acc_no'].apply(lambda x:pd.to_numeric(x)) #转成整数型
        
    def sort_data(self):
        '''按时间排序'''
        self.df = self.df.sort_values(by='时间', kind='mergesort')
        
    def generate_figure(self, df, title):
        '''绘图'''
        plt.figure(title, figsize=(20,15))
        
        #这里面的gca就是get currant axis
        ax=plt.gca()
        #下面这两句代码就是把右边和上边的轴给弄透明
        ax.spines["right"].set_color("none")
        ax.spines["top"].set_color("none")
        #下面两句代码就是把下边框选作x轴，左边框选作y轴
        #ax.xaxis.set_ticks_position("bottom")
        #ax.yaxis.set_ticks_position("left")
        #将底下的边框移到y=0处，将左边的边框移动到x=0处
        ax.spines["bottom"].set_position(("data",0))
        #ax.spines["left"].set_position(("data",0))
        
        #########################线形图
        plt.plot(df['时间'],df['Balance'],color="black",
                alpha=self.kwargs['FIGURE']['plot_alpha'],
                linewidth=self.kwargs['FIGURE']['plot_width'],
                linestyle="--",label=u"Balance")

        
        #########################散点图  
        # s 点的大小  c 点的颜色 alpha 透明度
        #颜色：b：blue；c：cyan；g：green；k：black；m：magenta；r：red；w：white；y：yellow
        # https://blog.csdn.net/qq_39959348/article/details/108940478
        plt.scatter(df['时间'],df['Org_amt'], 
                s=self.kwargs['FIGURE']['scatter_shape'],
                c=df['Part_acc_no'],
                cmap='gist_rainbow',
                alpha=self.kwargs['FIGURE']['scatter_alpha'], 
                label=u"Org_amt")
                
        # 显示数据标签
        if self.kwargs['FIGURE']['plot_text']=='Y':
            for a,b in zip(df['时间'],df['Balance']):
                plt.text(a,b,b,ha='center',va='bottom')
        if self.kwargs['FIGURE']['scatter_text']=='Y':
            for a,b in zip(df['时间'],df['Org_amt']):
                plt.text(a,b,b,ha='center',va='bottom')

        ##############################设置坐标轴
        #标题
        plt.title(title)
        #添加文本 #x轴文本
        #plt.xlabel('Date')
        #y轴文本
        #plt.ylabel('Org_amt')
        #添加图例
        plt.legend(loc="best")
        if self.kwargs['FIGURE']['save']=='Y':
            plt.savefig(os.path.join(self.kwargs['FIGURE']['folder'],title+'.png'), dpi=300, papertype='a3')
            print('【保存图片】',title+'.png')
        else:
            #plt.get_current_fig_manager().full_screen_toggle() #全屏
            plt.get_current_fig_manager().window.state('zoomed') #窗口最大化
            plt.show()
            
    def feature1(self):
        '''特征：集中转入，分散转出。入金笔数*6<出金笔数，入金金额=出金金额，出金笔数=出金对手数'''
        in_cnt = 0 #入金交易笔数
        in_amt = 0 #入金交易金额
        in_part = 0 #入金交易对手
        out_cnt =0 #出金交易笔数
        out_amt = 0 #出金交易金额
        out_part =0 #出金交易对手
        for index, row in self.df.iterrows():
            if row['Lend_flag'] == self.kwargs['FILE']['lend_flag']:
                in_cnt += 1
                in_amt += row['Org_amt']
            else:
                out_cnt += 1
                out_amt += row['Org_amt']
        print(in_cnt,in_amt,out_cnt,out_amt)
        # 或者以下方法求收支交易的对手数量
        ndf = self.df[self.df['Lend_flag']==self.kwargs['FILE']['lend_flag']]
        in_part = ndf.drop_duplicates(subset=['Part_acc_no'])['Part_acc_no'].count()
        in_cnt = ndf['Org_amt'].count()
        in_amt = ndf['Org_amt'].sum()
        ndf = self.df[self.df['Lend_flag']!=self.kwargs['FILE']['lend_flag']]
        out_part = ndf.drop_duplicates(subset=['Part_acc_no'])['Part_acc_no'].count()
        out_cnt = ndf['Org_amt'].count()
        out_amt = ndf['Org_amt'].sum()
        print(in_cnt,in_amt,out_cnt,out_amt)

        res = {'in_cnt':in_cnt,'in_amt':in_amt,'in_part':in_part,
               'out_cnt':out_cnt,'out_amt':out_amt,'out_part':out_part}
        print(res)
        return res
        
        
        
        
    def feature2(self, date1='2021-01-01', date2='2021-12-31', time1='00:00:00', time2='23:59:59'):
        '''日均交易'''
        df = self.df[(self.df['Date']>=date1) & (self.df['Date']<=date2) &
                     (self.df['Time']>=time1) & (self.df['Time']<=time2)]
        # 取每日最后一笔交易
        ndf = df.drop_duplicates(subset=['Date'],keep='last')
        days = ndf['Org_amt'].count()
        blc_avg = ndf['Balance'].mean()
        ndf = df[df['Lend_flag']==self.kwargs['FILE']['lend_flag']]
        in_amt_avg = ndf['Org_amt'].sum()/days
        res = {'days':days, 'blc_avg':blc_avg, 'in_amt_avg':in_amt_avg}
        print(res)
        return res
        
        
        
        
        
        
        
        
        
        
        
        
        